package ti.me.seek2chat.activities

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.util.Base64
import android.view.View.GONE
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.widget.Toast
import ti.me.seek2chat.adapters.ChatAdapter
import ti.me.seek2chat.databinding.ActivityChatBinding
import ti.me.seek2chat.leancloud.LeanCloudService
import ti.me.seek2chat.models.ChatMessage
import ti.me.seek2chat.models.User
import ti.me.seek2chat.utilities.ActivityLifecycleObserver
import ti.me.seek2chat.utilities.Constants
import ti.me.seek2chat.utilities.NotificationService
import ti.me.seek2chat.utilities.PreferenceManager

/**
 * ChatActivity 是一个用于处理聊天界面的活动类。
 * 它负责初始化聊天界面、加载接收者详情、监听消息并发送消息。
 */
class ChatActivity : BaseActivity() {
    private val binding by lazy { ActivityChatBinding.inflate(layoutInflater) }
    private lateinit var preferenceManager: PreferenceManager
    private lateinit var leanCloudService: LeanCloudService
    private lateinit var notificationService: NotificationService
    private lateinit var lifecycleObserver: ActivityLifecycleObserver
    private lateinit var chatMessages: ArrayList<ChatMessage>
    private lateinit var chatAdapter: ChatAdapter
    private lateinit var receiverUser: User
    private var conversionId: String? = null
    private var isReceiverAvailable = false
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        setListeners()
        loadReceiverDetails()
        init()
        listenMessages()
    }


    /**
     * 初始化聊天界面所需的组件和数据。
     */
    private fun init() {
        preferenceManager = PreferenceManager(applicationContext)
        leanCloudService = LeanCloudService(applicationContext)
        notificationService = NotificationService(applicationContext)
        lifecycleObserver = ActivityLifecycleObserver()
        lifecycle.addObserver(lifecycleObserver)
        chatMessages = ArrayList()
        chatAdapter = ChatAdapter(
            chatMessages,
            getBitmapFromEncodedString(receiverUser.image),
            preferenceManager.getString(Constants.KEY_USER_ID)!!
        )
        binding.chatRecyclerView.adapter = chatAdapter
    }

    /**
     * 发送消息的方法。
     * 从输入框获取消息内容并调用 LeanCloudService 保存消息。
     */
    private fun sendMessage() {
        val senderId = preferenceManager.getString(Constants.KEY_USER_ID) ?: ""
        val senderName = preferenceManager.getString(Constants.KEY_NAME) ?: ""
        val senderImage = preferenceManager.getString(Constants.KEY_IMAGE) ?: ""
        val receiverId = receiverUser.id
        val message = binding.inputMessage.text.toString()
        if (message.trim().isEmpty()) {
            showToast("Enter a message")
            return
        }
        leanCloudService.saveMessage(senderId, receiverId, message)
        if (conversionId != null) {
            leanCloudService.updateConversion(conversionId!!, message)
        } else {
            val conversion = HashMap<String, Any>()
            conversion[Constants.KEY_SENDER_ID] = senderId
            conversion[Constants.KEY_SENDER_NAME] = senderName
            conversion[Constants.KEY_SENDER_IMAGE] = senderImage
            conversion[Constants.KEY_RECEIVER_ID] = receiverId
            conversion[Constants.KEY_RECEIVER_NAME] = receiverUser.name
            conversion[Constants.KEY_RECEIVER_IMAGE] = receiverUser.image
            conversion[Constants.KEY_LAST_MESSAGE] = message
            conversion[Constants.KEY_TIMESTAMP] = System.currentTimeMillis()
            leanCloudService.addConversion(conversion)
        }

        binding.inputMessage.text.clear()
    }

    /**
     * 监听消息的方法。
     * 调用 LeanCloudService 监听消息并更新聊天界面。
     */
    private fun listenMessages() {
        val receivedId = receiverUser.id
        leanCloudService.listenForMessages(receivedId) { success, messages, errorMessage ->
            if (success && messages != null) {
                val count = chatMessages.size
                for (message in messages) {
                    val chatMessage = ChatMessage(
                        message.getString(Constants.KEY_SENDER_ID) ?: "",
                        message.getString(Constants.KEY_RECEIVER_ID) ?: "",
                        message.getString(Constants.KEY_MESSAGE) ?: "",
                        message.getString(Constants.KEY_TIMESTAMP) ?: "",
                        message.getString(Constants.KEY_SENDER_NAME) ?: "",
                        message.getString(Constants.KEY_RECEIVER_NAME) ?: "",
                        message.getString(Constants.KEY_SENDER_IMAGE) ?: "",
                    )
                    chatMessages.add(chatMessage)
                    if (chatMessage.senderId == receivedId && !lifecycleObserver.isActivityVisible) {
                        notificationService.sendNotification(chatMessage)
                    }
                }
                chatMessages.sortBy { it.dateTime }
                if (count == 0) {
                    chatAdapter.notifyDataSetChanged()
                } else {
                    chatAdapter.notifyItemRangeInserted(chatMessages.size, chatMessages.size)
                    binding.chatRecyclerView.smoothScrollToPosition(chatMessages.size - 1)
                }
                binding.chatRecyclerView.visibility = VISIBLE
            } else {
                showToast(errorMessage.toString())
            }
        }
        binding.progressBar.visibility = INVISIBLE
        if (conversionId == null) {
            checkForConversion()
        }
    }

    /**
     * 检查会话的方法。
     * 如果有会话则更新会话 ID。
     */
    private fun checkForConversion() {
        if (chatMessages.isNotEmpty()) {
            leanCloudService.checkForConversionRemotely(
                preferenceManager.getString(Constants.KEY_USER_ID) ?: "",
                receiverUser.id
            ) { success, conversationId ->
                if (success) {
                    conversionId = conversationId ?: ""
                }
            }

            leanCloudService.checkForConversionRemotely(
                receiverUser.id,
                preferenceManager.getString(Constants.KEY_USER_ID) ?: ""
            ) { success, conversationId ->
                if (success) {
                    conversionId = conversationId ?: ""
                }
            }
        }
    }

    /**
     * 监听聊天对象是否在线的方法。
     */
    private fun listenAvailabilityOfReceiver() {
        leanCloudService.listenAvailability(receiverUser.id) { success, availability ->
            if (success && availability == 1) {
                isReceiverAvailable = true
            }
            if (isReceiverAvailable) {
                binding.textAvailability.visibility = VISIBLE
            } else {
                binding.textAvailability.visibility = GONE
            }
        }
    }

    /**
     * 将 Base64 编码的字符串转换为 Bitmap。
     * @param encodedImage Base64 编码的字符串
     * @return 转换后的 Bitmap
     */
    private fun getBitmapFromEncodedString(encodedImage: String): Bitmap {
        val bytes = Base64.decode(encodedImage, Base64.DEFAULT)
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
    }

    /**
     * 加载接收者详情的方法。
     */
    private fun loadReceiverDetails() {
        receiverUser = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            intent.getSerializableExtra(Constants.KEY_USER, User::class.java) as User
        } else {
            intent.getSerializableExtra(Constants.KEY_USER) as User
        }

        binding.textName.text = receiverUser.name
    }

    /**
     * 事件绑定
     */
    private fun setListeners() {
        binding.imageBack.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }
        binding.layoutSend.setOnClickListener {
            sendMessage()
        }
    }

    /**
     * 显示 Toast 消息
     *
     * @param message 消息内容
     */
    private fun showToast(message: String) {
        Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
    }

    override fun onStart() {
        super.onStart()
        listenAvailabilityOfReceiver()
    }

    override fun onResume() {
        super.onResume()
        listenAvailabilityOfReceiver()
    }
}